package com.lyw.handle;

import com.lyw.constants.GlobalVariables;
import com.lyw.enums.DuplicateEnum;
import com.lyw.factory.TimerTaskFactory;
import com.lyw.utils.MouseAndKeyEventUtil;
import com.lyw.utils.OpenCvUtil;
import com.lyw.utils.SmallMapUtil;
import org.bytedeco.libfreenect._freenect_device;
import org.opencv.core.*;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.awt.*;
import java.awt.event.KeyEvent;

public class TopProcessor extends DataFilteringAdapter {
  int i, length, col, row, doorIndex;

  public TopProcessor() {
    position_name = "上";
    keycode = KeyEvent.VK_UP;
    mat = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\TPlan\\TPlan\\src\\main\\resources\\images\\position\\top.png");
  }

  @Override
  public boolean findTheTarget(Robot robot, int[] rolePosition, Mat res, int rows, int cols, int[] doorPosition) {
    length = rows * cols;
    for (i = 0; i < length; i++) {
      col = i / rows;
      row = i % rows;
      if (res.get(row, col)[0] >= 0.99997) {
        if (row < rolePosition[1]) { // 找到目标
          doorPosition[0] = col;
          doorPosition[1] = row;
          return true;
        }
      }
    }

    return false;
  }

  @Override
  public boolean findTheTargetDoor(Robot robot, Mat res, int rows, int cols, int[] rolePosition) {
    rolePosition[1] = rolePosition[1] + 90;
    length = rows * cols;
    for (i = 0; i < length; i++) {
      col = i / rows;
      row = i % rows;
      if (res.get(row, col)[0] >= 0.99997) {
        if (row < rolePosition[1]) {
          position[0] = col;
          position[1] = row;
          return true;
        }
      }
    }

    return false;
  }

  @Override
  public boolean findTheTargetDoor(Robot robot, Mat mat, Mat door, int[] startPosition, int[] positions) {

    Mat res = new Mat(mat.rows(), mat.cols(), CvType.CV_32FC1);
    Imgproc.matchTemplate(mat, door, res, Imgproc.TM_SQDIFF_NORMED);

    int rows = res.rows();
    int cols = res.cols();
    for (int row = 0; row < rows; row++) {
      for (int col = 0; col < cols; col++) {
        if (res.get(row, col)[0] <= 0.01) {
          positions[2] = col + startPosition[0];
          positions[3] = row + startPosition[1];
//          Point point = new Point(col, row);
//          Imgproc.rectangle(mat, point, new Point(point.x + door.cols(), point.y + door.rows()), new Scalar(0, 0, 255), 1, Imgproc.LINE_AA);
          return true;
//          System.out.println(col + ", " + row);
        }
      }
    }
    positions[2] = -1;
    positions[3] = -1;
//    HighGui.imshow("a", mat);
//    HighGui.waitKey(0);
    return false;
  }

  /**
   * 移动人物查找目标
   */
  @Override
  public void mobileCharacterSearchTarget(Robot robot, int[] key) throws Exception {

    // ------------------------ 没有找到目标 --------------------------
    // 直线没找到找两旁
    if (count[0] % 2 == 0) {
      if (!clearance[1]) {
        clearance[1] = true;
        MouseAndKeyEventUtil.keyReleased(key[0]);
        MouseAndKeyEventUtil.doubleClick(KeyEvent.VK_RIGHT);
        key[0] = KeyEvent.VK_RIGHT;
      }
    } else {
      if (!clearance[1]) {
        clearance[1] = true;
        MouseAndKeyEventUtil.keyReleased(key[0]);
        MouseAndKeyEventUtil.doubleClick(KeyEvent.VK_LEFT);
        key[0] = KeyEvent.VK_LEFT;
      }
    }
    // TODO 需要避开障碍物
  }

  /**
   * 移动人物到门口
   */
  @Override
  public void mobileCharacterToDoor(Robot robot, int[] key, int[] rolePosition, int[] doorPosition) throws Exception {
    if (rolePosition[0] > doorPosition[0]) {
      key[0] = KeyEvent.VK_LEFT;
    } else if (rolePosition[0] < doorPosition[0]) {
      key[0] = KeyEvent.VK_RIGHT;
    }
    MouseAndKeyEventUtil.doubleClick(key[0]);
    MouseAndKeyEventUtil.keyPress(KeyEvent.VK_UP);
  }

  @Override
  public boolean findTheTarget(int[] rgb, int width, int length, int[] colors) {
    for (doorIndex = 0; doorIndex < length; doorIndex++) {

      if (((rgb[doorIndex] >> 16) & 0xff) == colors[0]
              && ((rgb[doorIndex] >> 8) & 0xff) == colors[1]
              && (rgb[doorIndex] & 0xff) > colors[2] && (rgb[doorIndex] & 0xff) <= colors[3]) {
        System.out.println((doorIndex % width) + ", " + (doorIndex / width));
      }
    }
    return false;
  }

  @Override
  public boolean confirmIfTheDoorIsCorrect(int[] positions) {
    return Math.abs(positions[1] - positions[3]) <= 135;
  }

  @Override
  public void findDoor(Robot robot, Rectangle rectangle, int[] startPosition, TimerTaskFactory taskFactory, int height, int[] positions) throws Exception {
    MouseAndKeyEventUtil.doubleClick(keycode);
  }

  @Override
  public void mobileFindDoor(int[] counts, int[] keyCode) throws Exception {
    keyCode[0] = flag ? KeyEvent.VK_LEFT : KeyEvent.VK_RIGHT;
    flag = !flag;
    int releaseCode = flag ? KeyEvent.VK_LEFT : KeyEvent.VK_RIGHT;
    MouseAndKeyEventUtil.keyReleased(releaseCode);
    MouseAndKeyEventUtil.keyPress(keyCode[0]);
  }

  @Override
  public void mobileCharacterToCorrectDoor(int[] positions, int[] keycode) throws Exception {
    if (positions[0] - positions[2] >= 0) {
      keycode[0] = KeyEvent.VK_LEFT;
    } else {
      keycode[0] = KeyEvent.VK_RIGHT;
    }
    MouseAndKeyEventUtil.keyPress(keycode[0]);
  }

  @Override
  public boolean whetherClearance(int[] positions) {
    return Math.abs(positions[1] - positions[3]) <= 5;
  }

  @Override
  public void mobileCharacterToDoor(Robot robot, Rectangle rectangle, DuplicateEnum duplicateEnum) throws Exception {
    int[] positions = GlobalVariables.POSITIONS, destPosition = getDestPosition(robot, rectangle);
    int keycodeVal, abs;

    if (destPosition[0] - positions[0] >= 0) {
      keycodeVal = KeyEvent.VK_RIGHT;
    } else {
      keycodeVal= KeyEvent.VK_LEFT;
    }

    int[] cur_position = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateEnum);
    MouseAndKeyEventUtil.keyPress(keycodeVal);
    while(true) {
      positions = GlobalVariables.POSITIONS;
      destPosition = getDestPosition(robot, rectangle);
      abs = Math.abs(destPosition[0] - positions[0]);

      if (abs <= 15) {
        MouseAndKeyEventUtil.keyReleased(keycodeVal);
        MouseAndKeyEventUtil.keyPress(keycode);
        break;
      }
    }
    while (true) {
      int[] cur_positions = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateEnum);
      if (cur_positions[0] != -1 && cur_position[0] != cur_positions[0] && cur_positions[1] != cur_position[1]) {
        MouseAndKeyEventUtil.keyReleased(keycode);
        break;
      }
    }
  }

  public int[] getDestPosition(Robot robot, Rectangle rectangle) {
    Mat position = OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(rectangle));
    Mat result = new Mat(mat.rows(), mat.cols(), CvType.CV_32FC1);
    Imgproc.matchTemplate(mat, position, result, Imgproc.TM_SQDIFF_NORMED);
    Point minLoc = Core.minMaxLoc(result).minLoc;
    return new int[]{(int) minLoc.x, (int) minLoc.y};
  }
}
